using System.Drawing;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics.PackedVector;
using Microsoft.Xna.Framework.Content.Pipeline;
using Microsoft.Xna.Framework.Content.Pipeline.Graphics;
using Microsoft.Xna.Framework.Content.Pipeline.Processors;
using PaintDotNet;

namespace PdnImporter
{
    [ContentProcessor(DisplayName = "Paint.NET Processor")]
    public class PdnProcessor : ContentProcessor<Document, TextureContent>
    {
        public override TextureContent Process(Document input, ContentProcessorContext context)
        {
            Surface surface = new Surface(input.Size);
            input.Flatten(surface);
            Bitmap bmp = surface.CreateAliasedBitmap();

            PixelBitmapContent<Rgba32> bmpContent = new PixelBitmapContent<Rgba32>(bmp.Width, bmp.Height);
            for (int y = 0; y < bmp.Height; ++y)
            {
                for (int x = 0; x < bmp.Width; ++x)
                {
                    Color pixel = bmp.GetPixel(x, y);
                    bmpContent.SetPixel(x, y, new Rgba32((float)pixel.R / 255,
                                                         (float)pixel.G / 255,
                                                         (float)pixel.B / 255,
                                                         (float)pixel.A / 255));
                }
            }

            Texture2DContent texture = new Texture2DContent();
            texture.Mipmaps = new MipmapChain(bmpContent);
            texture.Validate();

            TextureProcessor proc = new TextureProcessor();
            return proc.Process(texture, context);
        }
    }

    [ContentProcessor(DisplayName = "Paint.NET Sprite Sheet Processor")]
    public class PdnSheetProcessor : ContentProcessor<Document, TextureContent>
    {
        private int layersPerRow = 10;
        /// <summary>
        /// How many layers to display on each row of the generated sprite sheet.
        /// </summary>
        public int SpritesPerRow
        {
            get { return layersPerRow; }
            set { layersPerRow = value; }
        }

        public override TextureContent Process(Document input, ContentProcessorContext context)
        {
            Bitmap[] bmp = new Bitmap[input.Layers.Count];
            for (int i = 0; i < input.Layers.Count; i++)
            {
                BitmapLayer layer = (BitmapLayer)input.Layers[i];
                bmp[i] = layer.Surface.CreateAliasedBitmap();
            }

            int width = System.Math.Min(bmp[0].Width * bmp.Length, bmp[0].Width * layersPerRow);
            int height = bmp[0].Height * (int)System.Math.Ceiling((double)input.Layers.Count / (double)layersPerRow);
            PixelBitmapContent<Rgba32> bmpContent = new PixelBitmapContent<Rgba32>(width, height);
            int x = 0, y = 0, c = 0;
            for (int i = 0; i < bmp.Length; i++)
            {
                for (int dy = 0; dy < bmp[i].Height; ++dy)
                {
                    for (int dx = 0; dx < bmp[i].Width; ++dx)
                    {
                        Color pixel = bmp[i].GetPixel(dx, dy);
                        bmpContent.SetPixel(dx + x, dy + y, new Rgba32((float)pixel.R / 255,
                                                             (float)pixel.G / 255,
                                                             (float)pixel.B / 255,
                                                             (float)pixel.A / 255));
                    }
                }

                c++;
                x += bmp[0].Width;
                if (c >= layersPerRow)
                {
                    c = 0;
                    x = 0;
                    y += bmp[i].Height;
                }
            }
            context.Logger.LogImportantMessage("Packed {0} layers into a {1} x {2} sprite sheet.", input.Layers.Count, width, height);

            Texture2DContent texture = new Texture2DContent();
            texture.Mipmaps = new MipmapChain(bmpContent);
            texture.Validate();

            TextureProcessor proc = new TextureProcessor();
            return proc.Process(texture, context);
        }
    }
}